﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;

namespace ApiCoreProject.Api
{
    public static class AuthorizationSetup
    {
        public static void AddAuthorizationSetup(this IServiceCollection services,IConfiguration configuration)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));

            // 配置策略授权
            services.AddAuthorization(o =>
            {
                // 添加策略，使用时在方法上标注[Authorize(Policy ="AdminPolicy")]，就会验证请求token中的ClaimTypes.Role是否包含了Admin
                o.AddPolicy("AdminPolicy", o =>
                {
                    //ClaimTypes.Role == Admin
                    o.RequireRole("Admin").Build();

                    //ClaimTypes.Role == Admin 或者 == User
                    //o.RequireRole("Admin","User").Build(); 

                    //ClaimTypes.Role == Admin 并且 == User ,关于添加多个角色策略，在Login控制器中
                    //o.RequireRole("Admin").RequireRole("User").Build(); 
                });

                //只有User的策略
                o.AddPolicy("onlyUserPolicy", o =>
                {
                    o.RequireRole("User").Build();
                });

                //User和Admin都可以访问的策略
                o.AddPolicy("UserOrAdminPolicy", o =>
                {
                    o.RequireRole("User", "Admin").Build();
                });

                //User并且是Admin才能请求的策略
                o.AddPolicy("UserAndAdminPolicy", o =>
                {
                    o.RequireRole("User").RequireRole("Admin").Build();
                });
            });

            string key = configuration["JwtSettings:SecurityKey"];
                //Appsettings.app(new string[] { "JwtSettings", "SecurityKey" });
            string issuer = configuration["JwtSettings:Issuer"]; 
                //Appsettings.app(new string[] { "JwtSettings", "Issuer" });
            string audience = configuration["JwtSettings:Audience"];
                //Appsettings.app(new string[] { "JwtSettings", "Audience" });

            SecurityKey securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)); //秘钥的长度有要求，必须>=16位

            services.AddAuthentication("Bearer").AddJwtBearer(o =>
            {
                o.TokenValidationParameters = new TokenValidationParameters()
                {
                    //是否秘钥认证
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = securityKey, //秘钥

                    //是否验证发行人
                    ValidateIssuer = true,
                    ValidIssuer = issuer, //这个字符串可以随便写，就是发行人

                    //是否验证订阅
                    ValidateAudience = true,
                    ValidAudience = audience,

                    //是否验证过期时间
                    RequireExpirationTime = true,
                    //是否验证Token有效期，使用当前时间与Token的Claims中的NotBefore和Expires对比
                    ValidateLifetime = true,
                    //注意这是缓冲过期时间，总的有效时间等于这个时间加上jwt的过期时间，如果不配置，默认是5分钟
                    ClockSkew = TimeSpan.FromSeconds(7)
                };
            });
        }
    }

    public static class AuthorizationConn
    {
        /// <summary>
        /// 生成 Token 令牌
        /// </summary>
        /// <param name="key">安全密钥</param>
        /// <param name="issuer">发行人</param>
        /// <param name="audience">受众</param>
        /// <param name="expires">过期时效</param>
        /// <param name="userRole">用户角色</param>
        /// <returns></returns>
        public static string CreateJwtToken(string key,string issuer,string audience, DateTime expires, string userRole)
        {
            
            //创建授权的token类
            SecurityToken securityToken = new JwtSecurityToken(
                issuer: issuer, //签发人
                audience: audience, //受众
                signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(key)), SecurityAlgorithms.HmacSha256), //秘钥

                

                //自定义JWT字段
                claims: new Claim[] {
                    //把模拟请求的角色权限添加到Role中 
                    new Claim(ClaimTypes.Role,userRole), 

                    //下面的都是自定义字段，可以任意添加到Claim作为信息共享
                    new Claim("Name","我叫lilili"),
                    new Claim("Age","18"),
                },

                //创建过期时间
                expires: expires //过期时间 
            );

            


            //返回请求token
            //return JsonConvert.SerializeObject(new { token = new JwtSecurityTokenHandler().WriteToken(securityToken) });

            return new JwtSecurityTokenHandler().WriteToken(securityToken);
        }
    }


}
